package cn.jg.framework.auth.session;

import cn.jg.framework.auth.model.Company;
import cn.jg.framework.auth.model.User;
import cn.jg.framework.common.model.SimpleBaseModel;
import cn.jg.framework.common.model.SimpleBaseMultiTenantModel;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import java.security.Principal;
import java.util.Optional;
import java.util.concurrent.Callable;

public class SessionManager {
	private SessionManager() {
		throw new IllegalStateException("Utility class");
	}

	public static <T> void packingCompany(T t) {
		if (t instanceof SimpleBaseMultiTenantModel) {
            SimpleBaseMultiTenantModel baseMultiTenantModel = (SimpleBaseMultiTenantModel) t;
			Company company = getCompany();
			if (company != null) {
				baseMultiTenantModel.setCompany(company);
			} else {
				User operationUser = SessionManager.getUser();
				baseMultiTenantModel.setCompany(operationUser.getCompany());
			}
		}
	}

	public static void runBatch(Runnable runnable) {
		try {
			runnable.run();
		} finally {
		}
	}

	public static <V> V callBatch(Callable<V> callable) throws Exception {
		try {
			return callable.call();
		} finally {
		}
	}

	public static <T> void packingCreateInfo(T t) {
		packingCompany(t);
		if (t instanceof SimpleBaseModel) {
			SimpleBaseModel SimpleBaseModel = (SimpleBaseModel) t;
			Integer userId = getUserId();
			SimpleBaseModel.setCreateUserId(userId);
			SimpleBaseModel.setUpdateUserId(userId);
		}
	}

	public static <T> void packingUpdateInfo(T t) {
		packingCompany(t);
		if (t instanceof SimpleBaseModel) {
			SimpleBaseModel SimpleBaseModel = (SimpleBaseModel) t;
			SimpleBaseModel.setUpdateUserId(getUserId());
		}
	}

	public static Integer getUserId() {
		return Optional.ofNullable(getUser()).orElseThrow(() -> new RuntimeException("user is null.")).getId();
	}

	public static Integer getCompanyId() {
		return Optional.ofNullable(getCompany()).orElseThrow(() -> new RuntimeException("company is null.")).getId();
	}

	public static User getUser() {
		User user = ThreadLocalUser.get();
		return user;
	}

	public static Company getCompany() {
		Company company = ThreadLocalCompany.get();
		return company;
	}

	public static boolean isSuperAdmin() {
		return true;
	}

	public static boolean isAdmin() {
		return true;
	}

	public static boolean isNormal() {
		return !isAdmin();
	}

	public static Principal getPrincipal() {
		return null;
	}

	public static Session getSession() {
		Subject subject = SecurityUtils.getSubject();
		return Optional.ofNullable(subject.getSession(false))
				.orElseGet(() -> subject.getSession());
	}


	public static Company getCompanyForLocal() {
		return getCompany();
	}

    public static String getAppId() {
        User user = ThreadLocalUser.get();
        if (null != user) {
            Company company = user.getCompany();
            if (null != company) {
                return company.getAppId();
            }
        }
        return null;
    }
}
